<?php
/**
 * app端屏保轮播图的管理
 * Author: lyun
 * Date: 2018/6/19
 * Created by Panxsoft.
 */


namespace App\Http\Controllers\Admin\Customer;

use App\Exceptions\ApiException;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Admin\Customer\Banner\BannerIndexRequest;
use App\Http\Requests\Admin\Customer\Banner\BannerStoreRequest;
use App\Http\Requests\Admin\Customer\Banner\BannerUpdateRequest;
use App\Models\Admin\CustomerAdmin;
use App\Models\Customer\Bannerable;
use App\Models\Customer\BannerType;
use App\Models\Customer\Banner;
use App\Models\Customer\Customer;
use App\Models\Customer\DeviceAccount;
use App\Models\Panx\Category;
use App\Models\Panx\Product;
use App\Models\Store\Store;
use App\Services\Utils\Guard;
use App\Services\Utils\Transaction;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Http\Request;

class BannerController extends ApiController
{
    const DEFAULT_ORDER_BYS = [
        [
            'order_by' => 'created_at',
            'sort'     => 'desc',
        ]
    ];

    const ROUTE_NAMES = [
        'index'   => 'api.admin.customer.banner.index',
        'store'   => 'api.admin.customer.banner.store',
        'update'  => 'api.admin.customer.banner.update',
        'destroy' => 'api.admin.customer.banner.destroy',
    ];

    /**
     * Display a listing of the resource.
     *
     * @test
     *
     * @param BannerIndexRequest $request
     *
     * @return \Illuminate\Http\Response
     *
     * @throws \Exception
     */
    public function index(BannerIndexRequest $request)
    {
        $this->checkCustomer();

        $this->checkIsTrue(CustomerAdmin::isGuardSuperAdmin(), trans('admin.is_super_man'));

        $customer_admin = Guard::customerAdmin();

        $banners = (new Banner)->where('customer_id', $customer_admin->customer_id)
//            ->filterStoreId($request->store_id)
//            ->filterDeviceAccountId($request->device_account_id)
//            ->filterAppBannerTypeId($request->banner_type_id)
            ->orderBys($request->order_bys, self::DEFAULT_ORDER_BYS)
            ->filterName($request->name)
            ->with('getStores', 'getDeviceAccounts')
            ->paginate($request->per_page ?: 15);

        return $this->response(compact('banners'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     *
     * @throws \Exception
     */
    public function create()
    {
        $this->checkIsTrue(CustomerAdmin::isGuardSuperAdmin(), trans('admin.is_super_man'));

        $customer = Guard::customer();

        $device_accounts = $customer->deviceAccounts()->get(['id', 'account', 'device_name']);
        $stores = (new Store)->where('customer_id', $customer->id)
            ->with('getDeviceAccounts')
            ->get(['id', 'name']);

        $banner_types = BannerType::filterHasHairTry($customer->has_hair)->get();

        $products = $customer->selfProducts()
            ->filterCategoryHasAsset(Category::HAS_ASSET)
            ->filterOnShelf()
            ->get(['id', 'spu_code', 'name', 'title']);

        return $this->response(compact('banner_types', 'stores', 'device_accounts', 'products'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @test
     * @see BannerControllerTest::test_store()
     *
     * @param  BannerStoreRequest  $request
     * @return \Illuminate\Http\Response
     *
     * @throws \Exception
     */
    public function store(BannerStoreRequest $request)
    {
        $this->checkCustomer();

        $this->checkIsTrue(CustomerAdmin::isGuardSuperAdmin(), trans('admin.is_super_man'));

        $banner_data = $this->assembleAppBanner($request);

        $stored = Transaction::handle(function () use($banner_data, $request) {

            $banner = Banner::create($banner_data);
            $this->storeBannerable($request, $banner);

            return $banner;
        });

        return $this->response(compact('stored'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @test
     * @see BannerControllerTest::test_update()
     *
     * @param  BannerUpdateRequest  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     *
     * @throws \Exception
     */
    public function update(BannerUpdateRequest $request, $id)
    {
        $this->checkCustomer();

        $this->checkIsTrue(CustomerAdmin::isGuardSuperAdmin(), trans('admin.is_super_man'));

        /** @var Banner $banner */
        $banner = (new Banner)->where('customer_id', Guard::customerAdmin()->customer_id)
            ->find($id);
        $this->checkItemExist($banner, trans('admin.app_banner'));

        $banner_data = $this->assembleAppBanner($request);

        $updated = Transaction::handle(function() use($banner, $banner_data, $request){
            $updated = $banner->update($banner_data);
            $this->updateBannerable($banner, $request);

            return $updated;
        });

        return $this->response(compact('updated'));
    }

    /**
     * Remove the specified resource from storage.
     *
     * @test
     * @see BannerControllerTest::test_destroy()
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     *
     * @throws \Exception
     */
    public function destroy($id)
    {
        $this->checkCustomer();

        $this->checkIsTrue(CustomerAdmin::isGuardSuperAdmin(), trans('admin.is_super_man'));

        /** @var Banner $banner */
        $banner = (new Banner)->where('customer_id', Guard::customerAdmin()->customer_id)
            ->find($id);
        $this->checkItemExist($banner, trans('admin.app_banner'));

        // 删除 APP_banner 与店铺、机器的多态多对多信息
        $banner->stores()->detach();
        $banner->deviceAccounts()->detach();

        $deleted = $banner->delete();

        return $this->response(compact('deleted'));
    }

    /**
     * @param BannerStoreRequest|BannerUpdateRequest|Request $request
     * @return array
     */
    private function assembleAppBanner(Request $request)
    {
        $data = [
            'customer_id'    => Guard::customerAdmin()->customer_id,
            'banner_type_id' => $request->banner_type_id,
            'name'           => $request->name,
            'image'          => $request->image,
            'data'           => json_encode([
                'spu_code' => $request->data
            ]),
            'priority'       => $request->priority,
        ];

        if ($request->started_at) {
            $data['started_at'] = $request->started_at;
        }

        if ($request->ended_at) {
            $data['ended_at'] = $request->ended_at;
        }

        return $data;
    }

    /**
     * @param Request|BannerStoreRequest|BannerUpdateRequest $request
     * @param $banner
     */
    private function storeBannerable(Request $request, Banner $banner)
    {
        $bannerable_type = ($request->type === BannerType::BANNER_TYPE_STORE)
            ? class_basename(Store::class)
            : class_basename(DeviceAccount::class);

        $data = $this->assembleValues($request->values, $bannerable_type);

        if ($bannerable_type === BannerType::BANNER_TYPE_STORE) {
            $banner->stores()->attach($data);
        } else {
            $banner->deviceAccounts()->attach($data);
        }
    }

    /**
     * @param Banner $banner
     * @param BannerUpdateRequest $request
     */
    private function updateBannerable(Banner $banner, BannerUpdateRequest $request)
    {
        // 删除 APP_banner 与店铺、机器的多态多对多信息
        $banner->stores()->detach();
        $banner->deviceAccounts()->detach();

        $this->storeBannerable($request, $banner);
    }

    /**
     * @param array $values
     * @param $bannerable_type
     * @return array
     */
    private function assembleValues(array $values, $bannerable_type)
    {
        $data = [];
        foreach($values as $value)
        {
            $data[$value] = ['bannerable_type' => $bannerable_type];
        }

        return $data;
    }
}
